<?php

class Storage
{
    static private $processCache;

    public static function beginTransaction($key){
        return MapDb::beginTransaction($key);
    }

    public static function commitTransaction($key){
        return MapDb::commitTransaction($key);
    }

    public static function rollbackTransaction($key){
        return MapDb::rollbackTransaction($key);
    }

    public static function getData($key, $orderBy = NULL, $onlyDb = FALSE)/*{{{*/
    {
        if (!empty(self::$processCache[$key]))
        {
            return  self::$processCache[$key];
        }

        if (empty($onlyDb))
        {
            $result =   self::getMcData($key);
            if (!empty($result) &&  is_array($result))
            {
                self::$processCache[$key]   =   $result;
                return  $result;
            }
        }

        $result     =   self::getDbData($key, $orderBy);
        if (empty($result)  ||  !is_array($result)) return  $result;
        self::$processCache[$key]   =   $result;

        if (empty($onlyDb))
        {
            $ret    =   self::setMcData($key, $result);
        }

        return  $result;
    }/*}}}*/

    public static function getDataByBodyid($code, $bodyId, $fields = ' * ', $uuidName)/*{{{*/
    {
        $result =   self::getDbDataByBodyid($code, $bodyId, $fields, $uuidName);
        return  $result;
    }/*}}}*/

    public static function getDataByBodyidWithId($code, $bodyId, $fields = ' * ', $uuidName)/*{{{*/
    {
        $result =   self::getDbDataByBodyidWithId($code, $bodyId, $fields, $uuidName);
        return  $result;
    }

    /**
     * @param   String  $key    e.g. : UI/123434
     * @param   Array or String
     *              e.g.    Array   =   array('uid' => '123423', 'name' => 'Ann','gb' => 5323, ...)
     *                      String  =   'uid="123423" AND name="Ann" AND gb=5323 .....
     * @param   String  $orderBy    e.g.: time DESC, blogId ASC
     *
     * @return  Array or Bool
     */
    public static function getConditionData($key, $where, $orderBy = NULL)/*{{{*/
    {
        if (empty($where))  return  self::getData($key, $orderBy);

        #   $conditionString=   NULL;
        #   ksort($where);
        #   foreach ($where as  $field  =>  $v)
        #   {
        #       if (empty($field))  continue;
        #       $conditionString[]  =   $field. '='. $v;
        #   }

        #   $cacheKey   =   implode('&', $conditionString);
        #   $result     =   self::getMcData($cacheKey);
        #   if (FALSE   !== $result)    return  $result;

        $result     =   self::getConditionDbData($key, $where, $orderBy);
        if (FALSE   === $result)    return  $result;

        #   self::setMcData($cacheKey, $result);
        return  $result;
    }/*}}}*/

    /**
     * @param   String  $key    e.g. : UI/123434
     * @param   Array or String
     *              e.g.    Array   =   array('uid' => '123423', 'name' => 'Ann','gb' => 5323, ...)
     *                      String  =   'uid="123423" AND name="Ann" AND gb=5323 .....
     * @return  Num
     */
    public static function countDataRow($key, $where = NULL)/*{{{*/
    {
        $result =   self::countDataDbRow($key, $where);
        return  $result;
    }/*}}}*/

    public static function getManyData($key, $orderBy = NULL, $start = NULL, $len = NULL)/*{{{*/
    {
        #   $result =   self::getMcData($key);
        #   if (FALSE   !== $result)    return  $result;

        $fields =   NULL;
        $result =   self::getManyDbData($key, $fields, $orderBy, $start, $len);
        #   if (FALSE   === $result)    return  $result;

        #   self::setMcData($key, $result);

        return  $result;
    }/*}}}*/

    /**
     * @param   $key        String  e.g.:   UI/@23434
     * @param   $fields     String or Array e.g.:   'id, uid, nickname' or array('id', 'uid', 'nickname')
     * @param   $orderBy    String
     * @param   $start      Int
     * @param   $len        Int
     *
     * @return  Array or Bool
     */
    public static function getFieldsManyData($key, $fields = NULL, $orderBy = NULL, $start = NULL, $len = NULL)/*{{{*/
    {
        return  self::getManyDbData($key, $fields, $orderBy, $start, $len);
    }/*}}}*/

    public static function getConditionManyData($key, $where, $orderBy = NULL, $start = NULL, $len = NULL)/*{{{*/
    {
        if (empty($where))  return  self::getManyData($key, $orderBy, $start, $len);

        $fields     =   NULL;
        $result     =   self::getConditionManyDbData($key, $fields, $where, $orderBy, $start, $len);
        if (FALSE   === $result)    return  $result;

        #   self::setMcData($cacheKey, $result);
        return  $result;
    }/*}}}*/
    public static function insertOrUpdate($key, $where)/*{{{*/
    {
        $result     =   self::insertAndUpdate($key, $where);
        if (FALSE   === $result)    return  $result;
    
        return  $result;
    }/*}}}*/
    
    /**
     * @param   $key        String  e.g.:   UI/@23434
     * @param   $fields     String or Array e.g.:   'id, uid, nickname' or array('id', 'uid', 'nickname')
     * @param   $where      Array or String
     * @param   $orderBy    String
     * @param   $start      Int
     * @param   $len        Int
     *
     * @return  Array or Bool
     */
    public static function getFieldsConditionManyData($key, $fields, $where, $orderBy = NULL, $start = NULL, $len = NULL)/*{{{*/
    {
        return  self::getConditionManyDbData($key, $fields, $where, $orderBy, $start, $len);
    }/*}}}*/

    public static function setData($key, $value)/*{{{*/
    {
        #   $oldValue   =   self::getMcData($key);
        #   self::setMcData($key, $value);

        $result     =   self::setDbData($key, $value);
        unset(self::$processCache[$key]);
        self::delMcData($key);
        #   if (!empty($result))    self::setMcData($key, $value);

        return  $result;
    }/*}}}*/

    public static function setConditionData($key, $value, $where)/*{{{*/
    {
        if (empty($where))  return  self::setData($key, $value);

        $keyArray   =   UK::splitMapKey($key);
        if (count($keyArray) < 2 || empty($value))  return  FALSE;

        $result     =   self::setConditionDbData($key, $value, $where);

        #   if (!empty($result) &&  !empty($where[TableMap::$tablePrimaryKey[$keyArray[0]]]))
        #   {
        #       $cacheKey   =   $key. '_'. $where[TableMap::$tablePrimaryKey[$keyArray[0]]];
        #       unset(self::$processCache[$cacheKey]);
        #       self::delMcData($cacheKey);
        #   }

        return  $result;
    }/*}}}*/

    public static function delData($key)/*{{{*/
    {
        $result =   self::delDbData($key);
        if (!empty($result))
        {
            unset(self::$processCache[$key]);
            self::delMcData($key);
        }

        return  $result;
    }/*}}}*/

    public static function delConditionData($key, $where)/*{{{*/
    {
        if (empty($where))  return  self::delData($key);

        $keyArray   =   UK::splitMapKey($key);
        if (count($keyArray) < 2 )  return  FALSE;

        #   $conditionString=   NULL;
        #   ksort($where);
        #   foreach ($where as  $field  =>  $v)
        #   {
        #       if (empty($field))  continue;
        #       $conditionString[]  =   $field. '='. $v;
        #   }

        #   $cacheKey   =   implode('&', $conditionString);
        #   self::delMcData($cacheKey);
        $result     =   self::delConditionDbData($key, $where);

        #   if (!empty($result) &&  !empty($where[TableMap::$tablePrimaryKey[$keyArray[0]]]))
        #   {
        #       $cacheKey   =   $key. '_'. $where[TableMap::$tablePrimaryKey[$keyArray[0]]];
        #       unset(self::$processCache[$cacheKey]);
        #       self::delMcData($cacheKey);
        #   }

        return  $result;
    }/*}}}*/

    public static function addData($key, $value)/*{{{*/
    {
        $result =   self::addDbData($key, $value);
        if (empty($result)) return  $result;

        #   self::addMcData($key, $value);
        return  $result;
    }/*}}}*/

    public static function complexUpdate($key, $value)/*{{{*/
    {
        if (empty($key))    return  NULL;
        unset(self::$processCache[$key]);
        self::delMcData($key);

        $result =   self::complexUpdateDb($key, $value);
        return  $result;
    }/*}}}*/
    
    /**
     * $num +- [start, end]
     */
    public static function changeNumBetweenMinMax($key, $value)/*{{{*/
    {
        $result =   self::changeDbNumBetweenMinMax($key, $value);
        #   if (!empty($result))    self::delMcData($key);

        return  $result;
    }/*}}}*/

	public static function changeNumValueAdd($key, $value, $where=null)/*{{{*/
    {
        $result =   self::changeDBNumValueAdd($key, $value, $where);

        return  $result;
    }/*}}}*/

    public static function execDbSentence($key, $sql)/*{{{*/
    {
        return  MapDb::execDbSentence($key, $sql);
    }/*}}}*/

    public static function execDbSentenceByClient($key, $sql)/*{{{*/
    {
        return  MapDb::execDbSentenceByClient($key, $sql);
    }/*}}}*/

    public static function fetchDbSentence($key, $sql, $rows = 1)/*{{{*/
    {
        return  MapDb::fetchDbSentence($key, $sql, $rows);
    }/*}}}*/

    public static function fetchDbSentenceByClient($key, $sql, $rows = 1)/*{{{*/
    {
        return  MapDb::fetchDbSentenceByClient($key, $sql, $rows);
    }/*}}}*/

    /**
     * For UserBonus fields (not include mood)
     */
    public static function limitUpdate($key, $value)/*{{{*/
    {
        unset(self::$processCache[$key]);
        $result =   self::limitDbUpdate($key, $value);
        if (!empty($result))    self::delMcData($key);

        return  $result;
    }/*}}}*/

    public static function limitConditionUpdate($key, $value, $where)/*{{{*/
    {
        $keyArray   =   UK::splitMapKey($key);
        if (count($keyArray) <  2)  return  FALSE;
        if (empty($where))  return  self::limitUpdate($key, $value);

        $result =   self::limitConditionDbUpdate($key, $value, $where);
        #   if (!empty($result) &&  !empty($where[TableMap::$tablePrimaryKey[$keyArray[0]]]))
        #   {
        #       $cacheKey   =   $key. '_'. $where[TableMap::$tablePrimaryKey[$keyArray[0]]];
        #       unset(self::$processCache[$cacheKey]);
        #       self::delMcData($cacheKey);
        #   }

        return  $result;
    }/*}}}*/

    # MC
    public static function getMcData($key)/*{{{*/
    {
        return  Mem::fetch($key);
    }/*}}}*/

    public static function setMcData($key, $value, $expire = NULL)/*{{{*/
    {
        if (empty($expire)) $expire =   AC::DEFAULT_CACHE_TIME;
        return  Mem::save($key, $value, $expire);
    }/*}}}*/

    public static function delMcData($key)/*{{{*/
    {
        return  Mem::remove($key);
    }/*}}}*/

    public static function addMcData($key ,$value, $expire = NULL)/*{{{*/
    {
        if (empty($expire)) $expire =   AC::DEFAULT_CACHE_TIME;
        return  Mem::add($key, $value, $expire);
    }/*}}}*/

    public static function mcIncrement($key, $value)/*{{{*/
    {
        return  Mem::increment($key, $value);
    }/*}}}*/

    public static function mcDecrement($key, $value)/*{{{*/
    {
        return  Mem::decrement($key, $value);
    }/*}}}*/

    # DB
    private function getDbData($key, $orderBy)/*{{{*/
    {
        return  MapDb::fetch($key, $orderBy);
    }/*}}}*/

    private function getDbDataByBodyid($code, $bodyId, $fields, $uuidName)/*{{{*/
    {
        return  MapDb::fetchByBodyid($code, $bodyId, $fields, $uuidName);
    }/*}}}*/

    private function getDbDataByBodyidWithId($code, $bodyId, $fields, $uuidName)/*{{{*/
    {
        return  MapDb::fetchByBodyidWithId($code, $bodyId, $fields, $uuidName);
    }

    private function getConditionDbData($key, $where, $orderBy)/*{{{*/
    {
        return  MapDb::fetchCondition($key, $where, $orderBy);
    }/*}}}*/

    private function countDataDbRow($key, $where)/*{{{*/
    {
        return  MapDb::fetchCountRow($key, $where);
    }/*}}}*/

    private function getManyDbData($key, $fields, $orderBy, $start, $len)/*{{{*/
    {
        return  MapDb::fetchMany($key, $fields, $orderBy, $start, $len);
    }/*}}}*/

    private function getConditionManyDbData($key, $fields, $where, $orderBy, $start, $len)/*{{{*/
    {
        return  MapDb::fetchConditionMany($key, $fields, $where, $orderBy, $start, $len);
    }/*}}}*/
    private function insertAndUpdate($key, $where)/*{{{*/
    {
        return  MapDb::insertOrUpdate($key, $where);
    }/*}}}*/
    
    private function setDbData($key, $value)/*{{{*/
    {
        return  MapDb::update($key, $value);
    }/*}}}*/

    private function setConditionDbData($key, $value, $where)/*{{{*/
    {
        return  MapDb::updateCondition($key, $value, $where);
    }/*}}}*/

    private function delDbData($key)/*{{{*/
    {
        return  MapDb::remove($key);
    }/*}}}*/

    private function delConditionDbData($key, $where)/*{{{*/
    {
        return  MapDb::removeCondition($key, $where);
    }/*}}}*/

    private function addDbData($key, $value)/*{{{*/
    {
        return  MapDb::insert($key, $value);
    }/*}}}*/

    private function complexUpdateDb($key, $value)/*{{{*/
    {
        return  MapDb::complexUpdate($key, $value);
    }/*}}}*/

    private function limitDbUpdate($key, $value)/*{{{*/
    {
        return  MapDb::limitUpdate($key, $value);
    }/*}}}*/

    private function limitConditionDbUpdate($key, $value, $where)/*{{{*/
    {
        return  MapDb::limitConditionUpdate($key, $value, $where);
    }/*}}}*/

    private function changeDBNumValueAdd($key, $value, $where)/*{{{*/
    {
        return MapDb::changeNumValueAdd($key, $value, $where);
    }/*}}}*/

    private function changeDbNumBetweenMinMax($key, $value)/*{{{*/
    {
        return  MapDb::changeNumBetweenMinMax($key, $value);
    }/*}}}*/

}
